/*******************************************************************************
 * Copyright (c) 2008-2009 zhang yuexiang.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package org.xfeep.alaya.orm.jpa;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
import javax.persistence.spi.ClassTransformer;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.sql.DataSource;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

import org.xfeep.alaya.jta.agent.PreMainAgent;


/**
 * PersistenceUnitInfoImp is a implementation of PersistenceUnitInfo. It is annotated with jaxb2.0 Annotations so
 * we can use it to parse a xml file about PersistenceUnitInfo
 * @author zhang yuexiang
 *
 */
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
public class PersistenceUnitInfoImp implements PersistenceUnitInfo {
	
	@XmlAttribute
	public String name;
	
	@XmlAttribute(name="transaction-type")
	public PersistenceUnitTransactionType transactionType = PersistenceUnitTransactionType.JTA;
	
	@XmlElement
	public String description;
	
	@XmlElement
	public String provider;
	
	@XmlElement(name="jta-data-source")
	public String jtaDataSourceName;
	
	@XmlTransient
	public DataSource jtaDataSource;
	
	@XmlElement(name="non-jta-data-source")
	public String nonJtaDataSourceName;
	
	
	@XmlElement(name="validation-mode")
	public ValidationMode validationMode = ValidationMode.NONE;
	
	@XmlElement(name="shared-cache-mode")
	public SharedCacheMode sharedCacheMode = SharedCacheMode.UNSPECIFIED;
	
	@XmlTransient
	public DataSource noJtaDataSource;
	
	@XmlTransient
	public String schemaVersion;
	
	@XmlElements(@XmlElement(name="mapping-file", type=String.class))
	public List<String> mappingFileNames = new ArrayList<String>();
	
	
	@XmlElements(@XmlElement(name="jar-file", type=String.class))
	public List<String> jarFiles = new ArrayList<String>();
	
	@XmlElements(@XmlElement(name="class", type=String.class))
	public List<String> managedClassNames = new ArrayList<String>();
	
	@XmlElement(name="exclude-unlisted-classes")
	public boolean excludeUnlistedClasses = true;
	
	@XmlElements(@XmlElement(name="property", type=PersistenceUnitInfoProperty.class))
	@XmlElementWrapper(name="properties")
	public List<PersistenceUnitInfoProperty> propertyList = new ArrayList<PersistenceUnitInfoProperty>();
	
	/**
	 * this field is a evaluted value from propertyList
	 */
	@XmlTransient
	public Properties properties = new Properties();
	
	/**
	 * now we list all other fields which should be initialized by EJB Container
	 */
	@XmlTransient
	public ClassLoader newTempClassLoader;
	
	@XmlTransient
	public ClassLoader classLoader;
	
	@XmlTransient
	public URL persistenceUnitRootUrl;
	

	@XmlTransient
	public List<URL> jarFileUrls = new ArrayList<URL>();
	
	/**
	 * Evaluate properties from propertyList
	 * this method should be called by EJB Container after propertyList initializing.
	 */
	public void evalProperties() {
		for (PersistenceUnitInfoProperty p : propertyList){
			properties.put(p.name, p.value);
		}
	}
	
	public void evalJarFileUrls(String root) throws MalformedURLException  {
			for (String f : jarFiles){
				jarFileUrls.add(new URL(root + f));
			}
	}
	
	public void addTransformer(ClassTransformer transformer) {
		/**
		 * TODO: after mergering PreMainAgent into aop (which maybe includes some container-managed
		 *  weaver hooks, e.g. TomcatWebAppWeaverHookedClassLoader ), the following code will be changed too.
		 */
		PreMainAgent.addTransformer(new JpaWrappedClassFileTransformer(transformer));
	}

	public boolean excludeUnlistedClasses() {
		return excludeUnlistedClasses;
	}

	public ClassLoader getClassLoader() {
		return classLoader;
	}

	public List<URL> getJarFileUrls() {
		return jarFileUrls;
	}

	public DataSource getJtaDataSource() {
		return jtaDataSource;
	}

	public List<String> getManagedClassNames() {
		return managedClassNames;
	}

	public List<String> getMappingFileNames() {
		return mappingFileNames;
	}

	public ClassLoader getNewTempClassLoader() {
		return newTempClassLoader;
	}

	public DataSource getNonJtaDataSource() {
		return noJtaDataSource;
	}

	public String getPersistenceProviderClassName() {
		return provider;
	}

	public String getPersistenceUnitName() {
		return name;
	}

	public URL getPersistenceUnitRootUrl() {
		return persistenceUnitRootUrl;
	}

	public Properties getProperties() {
		return properties;
	}

	public PersistenceUnitTransactionType getTransactionType() {
		return transactionType;
	}

	@Override
	public String getPersistenceXMLSchemaVersion() {
		return schemaVersion;
	}

	@Override
	public SharedCacheMode getSharedCacheMode() {
		return sharedCacheMode;
	}

	@Override
	public ValidationMode getValidationMode() {
		return validationMode;
	}


}
